package com.iot08.admin.service;

import com.iot08.admin.mob.MyPushWorkBuilder;
import com.iot08.admin.mob.StatsV3ResVO;
import com.iot08.admin.service.page.PageVO;
import com.iot08.admin.service.page.PageableImpl;
import com.iot08.admin.utils.ExcelUtil;
import com.iot08.admin.utils.FileUtil;
import com.iot08.common.constant.Const;
import com.iot08.common.entity.admin.MobNotify;
import com.iot08.common.entity.admin.MobNotifyPush;
import com.iot08.common.entity.admin.SysUser;
import com.iot08.common.entity.app.DeviceNotification;
import com.iot08.common.response.Response;
import com.iot08.common.service.base.BaseAdminService;
import com.iot08.common.utils.DateUtil;
import com.iot08.common.utils.StringUtil;
import mob.push.api.res.StatsV3Res;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @version 1.0
 * @Description: 推送相关配置业务处理
 * @author: Rock
 * @time: 2020/12/28 15:34
 */
@Service
public class MobNotifyPushService extends BaseAdminService<MobNotifyPush> {

    @Resource
    private MobNotifyService mobNotifyService;
    @Resource
    private MobSendService mobSendService;
    @Resource
    private DeviceNotificationService deviceNotificationService;
    @Resource
    private OpenidConfigService openidConfigService;
    @Resource
    private OperationService operationService;

    @Value("${device.import.path: }")
    private String importPath;

    /**
     * @param page
     * @param target
     * @param user
     * @time: 2020/12/29 17:33
     * @author: Rock
     * @version 1.0
     */
    public Page<MobNotifyPush> list(PageVO page, Integer target, SysUser user) {
        PageableImpl pageable = new PageableImpl();
        page.setSort(Sort.by(Sort.Order.desc("create_time")));
        pageable.setPage(page);

        Criteria criteria = Criteria.where("deleted").is(0);
        if (StringUtils.isNotEmpty(page.getSearchValue())) {
            criteria.and("content").regex(".*?" + page.getSearchValue() + ".*?", "i");
        }
        if (target != null) {
            criteria.and("target").is(target);
        }
        Query query = new Query().addCriteria(criteria);
        long count = mongoTemplate.count(query, MobNotifyPush.class);
        page.setTotalResult((int) count);
        List<MobNotifyPush> list = mongoTemplate.find(query.with(pageable), MobNotifyPush.class);
        Page<MobNotifyPush> result = new PageImpl<MobNotifyPush>(list, pageable, count);
        for (MobNotifyPush mobNotifyPush : list) {
            if (Const.INT_1.equals(mobNotifyPush.getTaskCron())
                    && mobNotifyPush.getTaskTime() > System.currentTimeMillis()) {
                mobNotifyPush.setIsDetail(false);
            }
        }
        return result;
    }

    /**
     * @param notifyPush
     * @param file
     * @param user
     * @time: 2020/12/31 11:21
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> add(MobNotifyPush notifyPush, MultipartFile file, SysUser user, String ip) throws IOException, InvalidFormatException {
        if (notifyPush != null) {
            MobNotify notify = mobNotifyService.findById(notifyPush.getNotifyId());
            if (notify == null) {
                return Response.failedResponse("推送消息不存在");
            }
            Set<String> openids = new HashSet<>();
            if (MyPushWorkBuilder.TARGET_ALIAS.equals(notifyPush.getTarget())) {
                //别名推送
                if (file == null || file.isEmpty()) {
                    return Response.failedResponse("请上传目标用户uuid文件");
                }
                String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
                if (!"xls".equals(suffix) && !"xlsx".equals(suffix)) {
                    return Response.failedResponse("请上传目标用户excel文件");
                }
                if (file.getSize() > 30 * 1024 * 1024) {
                    return Response.failedResponse("目标用户excel文件不能超过30M");
                }
                //把文件上传到服务器
                String filename = DateUtil.dateToStr(new Date(), DateUtil.FORMAT_3) + "-" + file.getOriginalFilename();
                FileUtil.upload(file, importPath, filename);

                Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(file.getBytes()));
                if (wb != null && wb.getSheetAt(0) != null) {
                    Sheet sheet = wb.getSheetAt(0);
                    openids = ExcelUtil.getImei(sheet);
                }
                if (openids.size() <= 0) {
                    return Response.failedResponse("目标用户excel文件内无uuid数据");
                }
                operationService.add(user, ip, "推送管理", "发送",
                        "目标文件推送", filename);
            } else if (MyPushWorkBuilder.TARGET_ALL.equals(notifyPush.getTarget())) {
                //广播
                operationService.add(user, ip, "推送管理", "发送",
                        "广播推送");
            } else {
                //推送异常
                return Response.failedResponse("推送目标用户类型异常");
            }
            //在系统通知表device_notification添加系统通知的记录
            DeviceNotification deviceNotification = deviceNotificationService.add(notifyPush, notify, user);
            notifyPush.setId(deviceNotification.getId());
            notifyPush.setContent(notify.getContent());
            notifyPush.setCreator(user.getId());
            notifyPush.setCreateTime(new Date());
            this.save(notifyPush);
            //发送mob推送
            String batchId = mobSendService.sendPush(notifyPush, notify, openids);
            if (StringUtil.isNotBlank(batchId)) {
                //创建新线程处理openids推送的可接受的用户
                if (openids.size() > 0) {
                    Set<String> finalOpenids = openids;
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            openidConfigService.checkUpdateShowMsgIdList(deviceNotification.getId(), finalOpenids);
                        }
                    }).start();
                }
                Update update = new Update();
                update.set("deleted", 0);
                update.set("mob_batch_id", batchId);
                this.updateById(notifyPush.getId(), update);
                return Response.successResponse("推送成功！请手动刷新推送管理页面即可");
            } else {
                return Response.failedResponse("推送发送失败");
            }
        }
        return Response.failedResponse("推送参数异常");
    }

    /**
     * 撤回
     *
     * @param id
     * @time: 2020/12/30 15:38
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> recall(String id, SysUser user, String ip) {
        MobNotifyPush push = this.findById(id);
        if (push != null) {
            //TODO 需等mob端修复撤回bug才能发送
            //boolean send = mobSendService.sendRecall(push.getMobBatchId());
            //if(send){
            //更新推送记录为删除
            Update update = new Update();
            update.set("deleted", 1);
            update.set("update_time", new Date());
            this.updateById(id, update);
            //删除系统通知消息记录
            deviceNotificationService.delById(new ObjectId(id));
            operationService.add(user, ip, "推送管理", "撤回",
                    "推送撤回 ID: " + id);
            return Response.successResponse();
            //}
        }
        return Response.failedResponse();
    }

    /**
     * @param id
     * @time: 2020/12/30 16:07
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> detail(String id) {
        MobNotifyPush push = this.findById(id);
        if (push != null) {
            StatsV3ResVO statsV3Res = mobSendService.sendDetial(push.getMobBatchId());
            if (statsV3Res != null) {
                if (statsV3Res.getIos() == null) {
                    statsV3Res.setIos(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getAndroid() == null) {
                    statsV3Res.setAndroid(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getFactory() == null) {
                    statsV3Res.setFactory(new StatsV3Res.WorkStatCountDetail());
                }
                statsV3Res.getFactory().setDeliverNum(statsV3Res.getAndroid().getDeliverNum() + statsV3Res.getIos().getDeliverNum());
                statsV3Res.getFactory().setReportNum(statsV3Res.getAndroid().getReportNum() + statsV3Res.getIos().getReportNum());
                statsV3Res.getFactory().setClickNum(statsV3Res.getAndroid().getClickNum() + statsV3Res.getIos().getClickNum());
                if (statsV3Res.getHuawei() == null) {
                    statsV3Res.setHuawei(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getXiaomi() == null) {
                    statsV3Res.setXiaomi(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getFlyme() == null) {
                    statsV3Res.setFlyme(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getVivo() == null) {
                    statsV3Res.setVivo(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getFcm() == null) {
                    statsV3Res.setFcm(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getOppo() == null) {
                    statsV3Res.setOppo(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getMobpush() == null) {
                    statsV3Res.setMobpush(new StatsV3Res.WorkStatCountDetail());
                }
                if (statsV3Res.getApns() == null) {
                    statsV3Res.setApns(new StatsV3Res.WorkStatCountDetail());
                }
            }
            return Response.successResponse(statsV3Res);
        }
        return Response.failedResponse();
    }

    /**
     * @param id
     * @param user
     * @param ip
     * @time: 2021/1/4 18:19
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> cancel(String id, SysUser user, String ip) {
        MobNotifyPush push = this.findById(id);
        if (push != null) {
            boolean send = mobSendService.sendCancel(push.getMobBatchId());
            if (send) {
                //更新推送记录为删除
                Update update = new Update();
                update.set("deleted", 1);
                update.set("update_time", new Date());
                this.updateById(id, update);
                //删除系统通知消息记录
                deviceNotificationService.delById(new ObjectId(id));
                operationService.add(user, ip, "推送管理", "取消",
                        "推送取消 ID: " + id);
                return Response.successResponse();
            }
        }
        return Response.failedResponse();
    }
}
